package force;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import assembly.Assembly;
import assembly.Mass;
import simulation.SpringiesConstants;
import simulation.Model;
import util.Location;
import util.Vector;


/**
 * 
 * @author Dagbedji Fagnisse
 * 
 */
public class CenterOfMass extends Force {
    private static final String KEYWORD = SpringiesConstants.COM_KEYWORD;
    private static final int TOGGLE_KEY = SpringiesConstants.COM_TOGGLE;
    /** Sample masses for default constructor. */
    private static List<Assembly> ourSampleAssemblies = new ArrayList<Assembly>();
    /** The exponent of the force. */
    private double myExponent;
    /** The magnitude of the force. */
    private Double myMagnitude;
    /** The masses in our model. */
    private List<Assembly> myAssemblies;

    /**
     * Create a "Center of mass" force.
     * 
     * @param magnitude magnitude of the force (negative means repulsive)
     * @param exp exponent of the force
     * @param assemblies - list of assemblies currently active in the simulation, used for isolating
     *        CoM forces to each assembly
     */
    public CenterOfMass (double magnitude, double exp, List<Assembly> assemblies) {
        myExponent = exp;
        myMagnitude = magnitude;
        myAssemblies = assemblies;
        toggle();
    }

    /**
     * Default constructor for sample CenterOfMass force.
     */
    public CenterOfMass () {
        // TODO how to actually define sample masses;
        this(0.0, 0.0, ourSampleAssemblies);
        ourSampleAssemblies.add(new Assembly());
        // don't forget to untoggle force
        toggle();
    }

    // @Override
    /**
     * An exponent value of 2.0 means inverse-square force (the force is inversely proportional to
     * the distance squared).
     * A value of 0.0 is a constant force independent of position.
     * 
     * @param m mass to calculate force vector for
     */
    public Vector getForceOn (Mass m) {
        if (!isForceOn()) { return new Vector(); }

        Vector result = new Vector(m.getCenter(), m.getAssembly().getCenterOfMass());
        if (result.getMagnitude() <= 1) { return new Vector(); }

        double factor = myMagnitude / Math.pow(result.getMagnitude(), myExponent);
        result.normalize();
        result.scale(factor);
        return result;
    }

    @Override
    public Force load (Scanner line, Model model) {
        double magnitude = line.nextDouble();
        double exponent = line.nextDouble();
        return new CenterOfMass(magnitude, exponent, model.getAssemblies());
    }

    @Override
    public String getKeyword () {
        return KEYWORD;
    }

    @Override
    public int getToggleKey () {
        return TOGGLE_KEY;
    }

}
